#include "equalizerview.h"
//#include <QPushButton>
#include <math.h>
#include <QDebug>



EqualizerView::EqualizerView(EqualizersGroup *group,QWidget *parent) : QWidget(parent)
{
    // btn_clear.setText(tr("清零"));
    // layout_main.addWidget(&widget_eq,0,0,1,1);
    // layout_main.addWidget(&btn_clear,0,1,1,1);
    // setLayout(&layout_main);

    eqGroup = group;

    freqRespStart = eqGroup->getFilterGroupStartFrequency();
    freqRespEnd = eqGroup->getFilterGroupEndFrequency();
    freqRespInterval = eqGroup->getFilterFrequencyResponseInterval();

    setBackgroundRole(QPalette::Base);
    setAutoFillBackground(true);

    brushBackground.setColor(QColor(10, 20, 30));
    brushBackground.setStyle(Qt::SolidPattern);

    penFrame.setColor(Qt::darkGray);
    penFrame.setStyle(Qt::SolidLine);
    penFrame.setWidthF(2);

    penLines.setColor(penFrame.color());
    penLines.setStyle(Qt::SolidLine);
    penLines.setWidthF(0.5);

    for(int i=0; i<EQ_BANDS; i++)
    {
        penEqCurve[i].setColor(curveColors[i]);
        penEqCurve[i].setStyle(Qt::SolidLine);
        penEqCurve[i].setWidthF(0.5);
        QColor color(curveColors[i]);
        color.setAlpha(80);
        brushEqCurve[i].setColor(color);
        brushEqCurve[i].setStyle(Qt::SolidPattern);
    }

    penAxisXY.setColor(Qt::darkGray);
    fontAxisText.setFamily("Arial");
    fontAxisText.setPixelSize(14);

    hzLogDiff = ::log10(freqRespEnd) - ::log10(freqRespStart);
    for(int i=0; i<HZ_POINTS; i++)
    {
        xAxisScaleCoe.append((::log10(yHz[i]) - ::log10(yHz[0])) / hzLogDiff);
    }
    //每条曲线的x轴坐标都是一样的。这里得出的是x轴坐标系数。
    double sf = freqRespStart;
    while(sf <= freqRespEnd)
    {
        eqCurveXaxis.append((::log10(sf) - ::log10(yHz[0])) / hzLogDiff);
        sf += freqRespInterval;
    }
    for(int n=0; n<eqGroup->getFilterCount(); n++)
    {
        double a = (::log10(eqGroup->getFilterCenterFrequency(n)) - ::log10(freqRespStart)) / hzLogDiff;
        eqHandleXAxis.append(a);
        eqGroup->updateEqualizer(n);
        QList<double> fq = eqGroup->getFilterFrequencyResponse(n);
        QList<QPointF> coe;
        for(int i=0; i<fq.count();i++)
        {
            double db = 0 - fq.at(i);
            coe.append(QPointF(eqCurveXaxis[i], db / 24));
        }
        eqPoints.append(coe);
    }
    updateEqResultCurvePath();
}

void EqualizerView::updateEqCurvePath(int num, double centerFreq, double Q, double gainDB)
{
    if(num >= eqGroup->getFilterCount())
    {
        return ;
    }
    eqGroup->setFilterCenterFrequency(num,centerFreq);
    eqGroup->setFilterQ(num,Q);
    eqGroup->setFilterGainDB(num,gainDB);
    eqGroup->updateEqualizer(num);
    QList<double> fq = eqGroup->getFilterFrequencyResponse(num);
    eqPoints[num].clear();
    for(int i=0; i<fq.count();i++)
    {
        double db = 0 - fq.at(i);
        eqPoints[num].append(QPointF(eqCurveXaxis[i], db / 24));
    }
    updateEqResultCurvePath();
    update();
}

void EqualizerView::updateEqResultCurvePath()
{
    eqResultCurvePoints.clear();
    double y;
    for(int i=0; i<eqCurveXaxis.count(); i++)
    {
        y = 0 ;
        for(int n=0; n<eqGroup->getFilterCount(); n++)
        {
            y += eqPoints[n][i].y();
        }
        eqResultCurvePoints.append(QPointF(eqCurveXaxis[i],y));
    }
}

void EqualizerView::set_all_gain_to_zero()
{

}

void EqualizerView::paintEvent(QPaintEvent *event)
{
    (void)event;

    QRectF rectFrame(width()*0.1,height()*0.1,width()*0.8,height()*0.8);

    QPainter painter(this);

    painter.fillRect(0,0,width()-1,height()-1,brushBackground);
    painter.setRenderHint(QPainter::Antialiasing, true);
    //y軕db刻度值
    painter.setPen(penAxisXY);
    painter.setFont(fontAxisText);
    int db = 24;
    for(int i=0; i<9; i++)
    {
        painter.drawText(rectFrame.x() - 20,(rectFrame.y() + fontAxisText.pixelSize()/2) + (i*(height() / 10)),QString::number(db));
        db -= 6;
    }
    //x轴Hz刻度值
    for(int i=0; i<xAxisScaleCoe.size(); i++)
    {
        painter.drawText(xAxisScaleCoe[i] * rectFrame.width() + rectFrame.x(),(rectFrame.y() + rectFrame.height())+fontAxisText.pixelSize(),yHzStr[i]);
    }

    //db刻度线
    QLineF dbLines[6] = {
        QLineF(rectFrame.x(),rectFrame.y() + (1*(height() / 10)),rectFrame.x() + rectFrame.width(),rectFrame.y() + (1*(height() / 10))),
        QLineF(rectFrame.x(),rectFrame.y() + (2*(height() / 10)),rectFrame.x() + rectFrame.width(),rectFrame.y() + (2*(height() / 10))),
        QLineF(rectFrame.x(),rectFrame.y() + (3*(height() / 10)),rectFrame.x() + rectFrame.width(),rectFrame.y() + (3*(height() / 10))),
        QLineF(rectFrame.x(),rectFrame.y() + (5*(height() / 10)),rectFrame.x() + rectFrame.width(),rectFrame.y() + (5*(height() / 10))),
        QLineF(rectFrame.x(),rectFrame.y() + (6*(height() / 10)),rectFrame.x() + rectFrame.width(),rectFrame.y() + (6*(height() / 10))),
        QLineF(rectFrame.x(),rectFrame.y() + (7*(height() / 10)),rectFrame.x() + rectFrame.width(),rectFrame.y() + (7*(height() / 10))),
    };
    painter.setPen(penLines);
    painter.drawLines(dbLines,6);
    QLineF lineM(rectFrame.x(),rectFrame.y() + (4*(height() / 10)),rectFrame.x() + rectFrame.width(),rectFrame.y() + (4*(height() / 10)));
    QPen penM(penLines);
    penM.setWidthF(penLines.widthF() * 4);
    painter.setPen(penM);
    painter.drawLine(lineM);

    //Hz刻度线
    painter.setPen(penLines);
    for(int i=1; i<(xAxisScaleCoe.size()-1); i++)
    {
        painter.drawLine(xAxisScaleCoe[i] * rectFrame.width() + rectFrame.x(),rectFrame.y(),xAxisScaleCoe[i] * rectFrame.width() + rectFrame.x(),rectFrame.y()+rectFrame.height());
    }

    // 绘制 eq 曲线
    QList<QPointF> points;
    for(int n=0; n<eqGroup->getFilterCount(); n++)
    {
        if(n == currentSelect)
        {
            QPen p(penEqCurve[n]);
            QBrush b(brushEqCurve[n]);
            QColor c(b.color());
            p.setWidthF(penEqCurve[n].widthF()*5);
            c.setAlpha(120);
            b.setColor(c);
            painter.setPen(p);
            painter.setBrush(b);
        }
        else
        {
            painter.setPen(penEqCurve[n]);
            painter.setBrush(brushEqCurve[n]);
        }
        points.clear();
        for(int i=0; i<eqPoints[n].count();i++)
        {
            points.append(QPointF(eqPoints[n].at(i).x() * rectFrame.width() + rectFrame.x(), rectFrame.y() + rectFrame.height() / 2 + eqPoints[n].at(i).y() * (rectFrame.height()/2)));
        }
        QPainterPath path;
        path.moveTo(rectFrame.x(),rectFrame.y() + rectFrame.height() / 2);
        int i=0;
        int s=points.size();
        while(i<s)
        {
            if(i==(s-1))
            {
                path.cubicTo(points[i],points[i],points[i]);
                break;
            }
            else if(i==(s-2))
            {
                path.cubicTo(points[i],points[i+1],points[i+1]);
                break;
            }
            else
            {
                path.cubicTo(points[i],points[i+1],points[i+2]);
                i+=3;
            }
        }
//        if(n == (EQ_BANDS-1))
        {
            path.lineTo(rectFrame.x() + rectFrame.width(),rectFrame.y() + rectFrame.height() / 2);
        }
        painter.drawPath(path);
    }
    //画最终曲线
    QPen p;
    p.setColor(Qt::white);
    p.setStyle(Qt::SolidLine);
    p.setWidth(2);
    painter.setPen(p);
    painter.setBrush(Qt::NoBrush);
    points.clear();
    for(int i=0; i<eqResultCurvePoints.count();i++)
    {
        points.append(QPointF(eqResultCurvePoints.at(i).x() * rectFrame.width() + rectFrame.x(), rectFrame.y() + rectFrame.height() / 2 + eqResultCurvePoints.at(i).y() * (rectFrame.height()/2)));
    }

    QPainterPath path(points[0]);

    int i=1;
    int n=points.size();
    while(i<n)
    {
        if(i==(n-1))
        {
            path.cubicTo(points[i],points[i],points[i]);
            break;
        }
        else if(i==(n-2))
        {
            path.cubicTo(points[i],points[i+1],points[i+1]);
            break;
        }
        else
        {
            path.cubicTo(points[i],points[i+1],points[i+2]);
            i+=3;
        }
    }
    path.lineTo(rectFrame.x() + rectFrame.width(),rectFrame.y() + rectFrame.height() / 2);
    painter.drawPath(path);

    //画dq控制点
    const double arcD = 10;
    for(int i=0; i<eqHandleXAxis.size(); i++)
    {
        double db = eqGroup->getFilterGainDB(i);
        QPen p(penEqCurve[i]);
        p.setWidthF(penEqCurve[i].widthF()*2);
        QBrush b(brushEqCurve[i]);
        QColor c(b.color());
        c.setAlpha(255);
        b.setColor(c);
        painter.setPen(p);
        painter.setBrush(b);
        painter.drawEllipse(eqHandleXAxis[i] * rectFrame.width() + rectFrame.x() - (arcD/2), rectFrame.y() + rectFrame.height() / 2 + ((0-db)/24) * (rectFrame.height()/2) - (arcD/2),arcD,arcD);
    }


//    p.setColor(Qt::red);
//    painter.setPen(p);
//    painter.setBrush(Qt::yellow);
//    QPainterPath pathTest;
//    pathTest.moveTo(-10,10);
//    pathTest.cubicTo(50,30,100,60,150,150);
//    painter.drawPath(pathTest);
//    painter.drawText(-10,10,"1");
//    painter.drawText(50,30,"2");
//    painter.drawText(100,60,"3");
//    painter.drawText(150,150,"4");
//    painter.drawText(180,150,"5");

//    painter.restore();
//    painter.setRenderHint(QPainter::Antialiasing, false);
//    painter.setPen(palette().dark().color());
//    painter.setBrush(Qt::NoBrush);
//    painter.drawRect(QRect(0, 0, width() - 1, height() - 1));

    localRect = rectFrame;
    painter.setPen(penFrame);
    painter.setBrush(Qt::NoBrush);
    painter.drawRoundedRect(rectFrame,10,10);    
}

void EqualizerView::mousePressEvent(QMouseEvent *event)
{
//    qDebug() << "mouse press event:" << event;
    currentSelect = -1;
    if(event->button() == Qt::LeftButton)
    {
        QPointF lp = event->localPos();
        for(int i=0; i<eqHandleXAxis.size(); i++)
        {
            double x = eqHandleXAxis[i] * localRect.width() + localRect.x() - (10/2);
            double x1 = x-10;
            double x2 = x+10;
            double db = eqGroup->getFilterGainDB(i);
            if(lp.x() >= x1 && lp.x() <= x2)
            {
                double y = localRect.y() + localRect.height() / 2 + ((0-db)/24) * (localRect.height()/2) - (10/2);
                double y1 = y - 10;
                double y2 = y + 10;
                if(lp.y() >= y1 && lp.y() <= y2)
                {
                    currentSelect = i;
                    emit sig_eq_select_change(i);
                }
            }
        }
    }
    update();
}

void EqualizerView::mouseReleaseEvent(QMouseEvent *event)
{
//    qDebug() << "mouse release event:" << event;
    (void)event;
//    currentSelect = -1;
//    update();
    if(currentSelect >= 0)
    {
        emit equalizerParamUpdate(currentSelect,eqGroup->getFilterCenterFrequency(currentSelect),eqGroup->getFilterQ(currentSelect),eqGroup->getFilterGainDB(currentSelect));
        emit sig_eq_select_release(currentSelect);
    }
}

void EqualizerView::mouseMoveEvent(QMouseEvent *event)
{
//    qDebug() << "mouse move event:" << event;
    if(currentSelect >= 0)
    {
        QPointF lp = event->localPos();
        double my = localRect.y() + localRect.height() / 2;
        double db = (my - lp.y()) / (localRect.height() / 2) * 24;

        double cx = lp.x() - localRect.x();
        double cy = localRect.y() - lp.y();
        if(cx < 0)
        {
            cx = 0;
        }
        if(cy < 0)
        {
            cy = 0;
        }
        double xr = cx / localRect.width();
        double cf = ::floorl(::pow(10,xr*hzLogDiff + ::log10(yHz[0])));

        double dbMax = eqGroup->getFilterGainDBMax(currentSelect);
        double dbMin = eqGroup->getFilterGainDBMin(currentSelect);
        double cfMax = eqGroup->getFilterCenterFrequencyMax(currentSelect);
        double cfMin = eqGroup->getFilterCenterFrequencyMin(currentSelect);
        if(db > dbMax)
        {
            db = dbMax;
        }
        else if(db < dbMin)
        {
            db = dbMin;
        }
        if(cf < cfMin)
        {
            cf = cfMin;
        }
        else if(cf > cfMax)
        {
            cf = cfMax;
        }

        eqHandleXAxis[currentSelect] = (::log10(eqGroup->getFilterCenterFrequency(currentSelect)) - ::log10(freqRespStart)) / hzLogDiff;
        updateEqCurvePath(currentSelect,cf,eqGroup->getFilterQ(currentSelect),db);
        emit sig_eq_select_change(currentSelect);
    }
}

void EqualizerView::wheelEvent(QWheelEvent *event)
{
//    qDebug() << "whellevent" << event;
    if(currentSelect >= 0)
    {
        double q = eqGroup->getFilterQ(currentSelect);
        if(event->angleDelta().y() > 0)
        {
            q += 0.1;
        }
        else
        {
            q -= 0.1;
        }
        double qMax = eqGroup->getFilterQMax(currentSelect);
        double qMin = eqGroup->getFilterQMin(currentSelect);
        if(q > qMax)
        {
            q = qMax;
        }
        else if(q < qMin)
        {
            q = qMin;
        }
        updateEqCurvePath(currentSelect,eqGroup->getFilterCenterFrequency(currentSelect),q,eqGroup->getFilterGainDB(currentSelect));
        //emit sig_eq_select(currentSelect);
        emit sig_eq_select_change(currentSelect);
        emit equalizerParamUpdate(currentSelect,eqGroup->getFilterCenterFrequency(currentSelect),eqGroup->getFilterQ(currentSelect),eqGroup->getFilterGainDB(currentSelect));
    }
}

void EqualizerView::updateView()
{
    // for(int i=0; i<eqGroup->getFilterCount(); i++)
    // {
    //     QList<double> fq = eqGroup->getFilterFrequencyResponse(i);
    //     eqPoints[i].clear();
    //     for(int i=0; i<fq.count();i++)
    //     {
    //         double db = 0 - fq.at(i);
    //         eqPoints[i].append(QPointF(eqCurveXaxis[i], db / 24));
    //     }
    // }
    // currentSelect = -1;
    // updateEqResultCurvePath();
    // update();
    for (int i = 0; i < eqGroup->getFilterCount(); ++i) {
        eqHandleXAxis[i] = (::log10(eqGroup->getFilterCenterFrequency(i)) - ::log10(freqRespStart)) / hzLogDiff;
        updateEqCurvePath(i,eqGroup->getFilterCenterFrequency(i),eqGroup->getFilterQ(i),eqGroup->getFilterGainDB(i));
    }
}

